��վ�ܷ�������

题解:LUOGU P3932 浮游大陆的68号岛

值得一提的是,这题疯狂卡mod,能mod的地方都要mod!

mmp我就因为这个卡了一面

看了所有题解没有和我一个线段树思路的非常高兴地来写题解里。

首先维护一个前缀和来表示dis这个大家都会

根据题意我们可以轻松知道

当$[Math Processing Error]l>x$时,

$[Math Processing Error] ans=a[r] \times (sum[r]-sum[x])+a[r-1] \times (sum[r-1]-sum[x])+…+a[l]\times (sum[l]-sum[x]);$

$[Math Processing Error] ans=-(a[r]+a[r-1]+…+a[l]) \times sum[x]$

​ $ +a[r] \times sum[r]+a[r-1] \times sum[r-1]+…+a[l]\times sum[l];$

当$[Math Processing Error]r<x$时,

把式子反过来就行

其他情况将区间剖开,求$(l,x-1)$和$(x+1,r)$就行,

因为从一个点运到同一个点$dis=0$是要去掉的

于是我们可以发现只要维护一个区间和,和一个$[Math Processing Error]a[x]*sum[x]$的和就行了

这不是很简单的线段树操作吗?,连$[Math Processing Error]pushdown$都不用就显得非常简单了

直接上代码!

// 把式子一列其实就一目了然了代码清晰易懂
//代码中疯狂mod注意
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 200000+10000
#define lson 2*p
#define rson 2*p+1
#define ll long long
using namespace std;
const ll mod=19260817;
struct node
{
    int lt;
    int rt;
    ll val;
    ll sum;
    ll w;//这就是我上面提到的a[x]*sum[x] 把这个量重新做一个变量
}a[4*N];
int n,m;
ll data[N],w[N],sum[N];
void pushup(int p)//简单的操作,大家都懂
{
   a[p].sum=(a[lson].sum+a[rson].sum)%mod;
   a[p].w=(a[lson].w+a[rson].w)%mod;
}
void build(int p,int l,int r)//基本操作
{
    a[p].lt=l;
    a[p].rt=r;
    if(l==r){a[p].sum=data[l];a[p].w=data[l]*sum[l]%mod;return;}
    int mid=(l+r)/2;
    build(2*p,l,mid);
    build(2*p+1,mid+1,r);
    pushup(p);
}
ll query(int p,int l,int r)
{
    if(a[p].lt==l&&a[p].rt==r)return a[p].sum%mod;
    int mid=(a[p].lt+a[p].rt)/2;
    if(r<=mid)return query(2*p,l,r);
    else if(l>mid)return query(2*p+1,l,r);
         else return (query(2*p,l,mid)+query(2*p+1,mid+1,r))%mod;
}
ll query_w(int p,int l,int r)
{
    if(a[p].lt==l&&a[p].rt==r)return a[p].w%mod;
    int mid=(a[p].rt+a[p].lt)/2;
    if(r<=mid)return query_w(lson,l,r);
    else if(l>mid)return query_w(rson,l,r);
    else return (query_w(lson,l,mid)+query_w(rson,mid+1,r))%mod;
}
//这些都没什么要讲的,全是模板
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=2;i<=n;i++)
    {
        int x;
        scanf("%lld",&x);
        x%=mod;
        sum[i]=sum[i-1]+x;//前缀和操作
        sum[i]%=mod;
    }
    for(int i=1;i<=n;i++){scanf("%lld",&data[i]);data[i]%=mod;}
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(y>z)swap(y,z);
        ll sum1=0,sum2=0;
        if(x==y&&x==z)//特判一下
        {
            printf("0\n");
            continue;
        }
        if(y==x)y++;//因为要避免等于的情况要删掉
        if(z==x)z--;
        if(y>x)
            sum1=query_w(1,y,z)%mod-query(1,y,z)*sum[x]%mod;//这些东西看我列的式子很好理解
         else if(z<x)
           sum2=sum[x]*query(1,y,z)%mod-query_w(1,y,z)%mod;
        else
        {
            sum1=query_w(1,x+1,z)%mod-query(1,x+1,z)*sum[x]%mod;//要把x给空出来!
            sum2=sum[x]*query(1,y,x-1)%mod-query_w(1,y,x-1)%mod;

        }
        ll ans=sum1+sum2;
        printf("%lld\n",(ans+mod*3)%mod);//毒瘤的mod
    }

    return 0;
}